package com.acctrue.zentao.ui;

import com.acctrue.zentao.dto.LoginDTO;
import com.acctrue.zentao.dto.ProjectDTO;
import com.acctrue.zentao.dto.TaskDTO;
import com.acctrue.zentao.entity.ZentaoSettingEntity;
import com.acctrue.zentao.enums.BugStatusEnum;
import com.acctrue.zentao.enums.ModuleTypeEnum;
import com.acctrue.zentao.enums.TaskStatusEnum;
import com.acctrue.zentao.enums.TaskTypeEnum;
import com.acctrue.zentao.utils.ResponseResult;
import com.acctrue.zentao.utils.ZentaoUtils;
import com.google.common.collect.Lists;
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.openapi.ui.DialogWrapper;

import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
import java.awt.event.ActionEvent;
import java.awt.event.ItemEvent;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author : sunjj
 * @createTime : 2023/8/20
 */
public class ZentaoTaskUi {
    private JPanel mainPanel;
    private JCheckBox chkFeat;
    private JCheckBox chkRefactor;
    private JCheckBox chkBug;
    private JCheckBox chkComplete;
    private JComboBox cmbProjects;
    private JButton btnRefresh;
    private JLabel labMessage;
    private JScrollPane panelTask;
    private JTable tblTask;
    private LoginDTO loginDTO;
    private List<String> messages = new ArrayList<>();
    private Map<String, String> projects = new HashMap<>();
    private volatile boolean tasking = false;
    /**
     * 排序字段 默认id 排序
     */
    private String sortName = "id";
    /**
     * 排序类型 true：降序 false：升序
     */
    private Boolean sortType = true;

    public ZentaoTaskUi(DialogWrapper dialog) {
        initUI();
        Optional<ZentaoSettingEntity> optional = ZentaoSettingEntity.getEntity(PropertiesComponent.getInstance());
        if (optional.isPresent() && optional.get().getSuccess()) {
            initData(optional.get());
        } else {
            labMessage.setText("未绑定禅道账号");
            btnRefresh.setEnabled(false);
        }
    }

    /**
     * 初始化ui页面
     */
    private void initUI() {
        btnRefresh.addActionListener(this::btnRefreshClickEvent);
        chkFeat.addActionListener(this::checkBoxActionEvent);
        chkRefactor.addActionListener(this::checkBoxActionEvent);
        chkBug.addActionListener(this::checkBoxActionEvent);
        chkComplete.addActionListener(this::checkBoxActionEvent);
        DefaultTableModel tableModel = (DefaultTableModel) this.tblTask.getModel();
        //设置表头
        tableModel.setColumnIdentifiers(new String[]{"", "选择", "ID", "类型", "任务/Bug", "状态", "截止时间", "所属项目", "创建人"});
        int[] length = {15, 20, 15, 50, 150, 50, 150, 80, 100};
        //获取表格的 列 模型
        TableColumnModel columnModel = this.tblTask.getColumnModel();
        //设置每列的宽度
        for (int i = 0; i < columnModel.getColumnCount(); i++) {
            //获取列对象
            TableColumn column = columnModel.getColumn(i);
            //设置列宽
            column.setPreferredWidth(length[i]);
        }
        this.tblTask.setModel(tableModel);
        this.tblTask.getColumnModel().getColumn(1).setCellRenderer(this.tblTask.getDefaultRenderer(Boolean.class));
        this.tblTask.getColumnModel().getColumn(1).setCellEditor(this.tblTask.getDefaultEditor(Boolean.class));
    }

    /**
     * 初始化数据
     *
     * @param settingEntity
     */
    private void initData(ZentaoSettingEntity settingEntity) {
        loginDTO = new LoginDTO();
        LoginDTO.Input input = new LoginDTO.Input();
        input.setServerAddress(settingEntity.getServerAddress());
        input.setPassword(settingEntity.getPassword());
        input.setUserName(settingEntity.getUserName());
        loginDTO.setInput(input);
        ResponseResult<LoginDTO.Output> loginResult = ZentaoUtils.login(input);
        if (!loginResult.getSuccess()) {
            btnRefresh.setEnabled(false);
            labMessage.setText(loginResult.getMessage());
        } else {
            btnRefresh.setEnabled(true);
            labMessage.setText("");
            loginDTO.setOutput(loginResult.getData());
            searchProjectList();
        }
    }

    /**
     * 获取禅道项目列表
     */
    private void searchProjectList() {
        ProjectDTO.Input input = new ProjectDTO.Input();
        input.setServerAddress(loginDTO.getInput().getServerAddress());
        input.setSessionID(loginDTO.getOutput().getSessionID());
        input.setSessionName(loginDTO.getOutput().getSessionName());
        input.setToken(loginDTO.getOutput().getToken());
        ResponseResult<List<ProjectDTO.Output>> projectResult = ZentaoUtils.searchProjectList(input);
        if (!projectResult.getSuccess()) {
            labMessage.setText(projectResult.getMessage());
            return;
        }
        List<ProjectDTO.Output> projectList = projectResult.getData();
        projects.clear();
        for (ProjectDTO.Output item : projectList) {
            cmbProjects.addItem(item);
            projects.put(item.getId(), item.getName());
        }
        cmbProjects.setSelectedIndex(-1);
        cmbProjects.addItemListener(this::cmbProjectsSelect);
        searchTaskList();
    }

    /**
     * 获取禅道任务/bug列表
     */
    private void searchTaskList() {
        if (tasking) {
            return;
        }
        tasking = true;
        try {
            TaskDTO.Input input = new TaskDTO.Input();
            input.setServerAddress(loginDTO.getInput().getServerAddress());
            input.setSessionID(loginDTO.getOutput().getSessionID());
            input.setSessionName(loginDTO.getOutput().getSessionName());
            input.setToken(loginDTO.getOutput().getToken());
            List<String> taskTypes = new ArrayList<>(2);
            if (chkFeat.isSelected()) {
                taskTypes.add(TaskTypeEnum.devel.getValue());
            }
            if (chkRefactor.isSelected()) {
                taskTypes.add(TaskTypeEnum.devnew.getValue());
            }
            input.setTaskTypes(taskTypes);
            List<String> taskStatus = new ArrayList<>(4);
            taskStatus.add(TaskStatusEnum.wait.getValue());
            taskStatus.add(TaskStatusEnum.doing.getValue());
            taskStatus.add(TaskStatusEnum.pause.getValue());
            if (chkComplete.isSelected()) {
                taskStatus.add(TaskStatusEnum.done.getValue());
            }
            input.setTaskStatus(taskStatus);
            input.setAreBug(chkBug.isSelected());
            Object selectedItem = cmbProjects.getSelectedItem();
            if (selectedItem != null) {
                input.setProjectId(((ProjectDTO.Output) selectedItem).getId());
            }
            ResponseResult<List<TaskDTO.Output>> taskResult = ZentaoUtils.searchTaskList(input);
            if (!taskResult.getSuccess()) {
                labMessage.setText(taskResult.getMessage());
                return;
            }
            fillJTable(taskResult.getData());
        } finally {
            tasking = false;
        }
    }

    /**
     * 刷新按钮点击时间
     *
     * @param e
     */
    private void btnRefreshClickEvent(ActionEvent e) {
        searchTaskList();
    }

    /**
     * 多选框点击事件
     *
     * @param e
     */
    private void checkBoxActionEvent(ActionEvent e) {
        this.searchTaskList();
    }

    /**
     * 项目列表选择事件
     *
     * @param e
     */
    private void cmbProjectsSelect(ItemEvent e) {
        searchTaskList();
    }

    private String getTypeName(TaskDTO.Output output) {
        if (ModuleTypeEnum.BUG == output.getModuleType()) {
            return "bug";
        }

        if (ModuleTypeEnum.TASK == output.getModuleType()) {
            return TaskTypeEnum.getNameByValue(output.getType());
        }

        if (ModuleTypeEnum.DOC == output.getModuleType()) {
            return TaskTypeEnum.getNameByValue(output.getType());
        }

        if (ModuleTypeEnum.DEFAULT == output.getModuleType()) {
            return TaskTypeEnum.getNameByValue(output.getType());
        }

        return "未知";
    }

    private String getStatusName(TaskDTO.Output output) {
        if (ModuleTypeEnum.BUG == output.getModuleType()) {
            return BugStatusEnum.getNameByValue(output.getStatus());
        }

        if (ModuleTypeEnum.TASK == output.getModuleType()) {
            return TaskStatusEnum.getNameByValue(output.getStatus());
        }

        if (ModuleTypeEnum.DOC == output.getModuleType()) {
            return TaskStatusEnum.getNameByValue(output.getStatus());
        }

        if (ModuleTypeEnum.DEFAULT == output.getModuleType()) {
            return "";
        }
        return "未知";
    }

    private String getCommitMessage(TaskDTO.Output output) {
        StringBuilder sb = new StringBuilder();
        sb.append(ModuleTypeEnum.getCommitPrefix(output.getModuleType(), output.getType()));
        sb.append("[").append(output.getId()).append("]");
        sb.append(output.getTitle());
        return sb.toString();
    }

    /**
     * 清除table表格
     *
     * @param model
     */
    private void clearJTable(DefaultTableModel model) {
        while (model.getRowCount() > 0) {
            model.removeRow(0);
        }
    }

    /**
     * 填充table表格
     */
    private void fillJTable(List<TaskDTO.Output> taskList) {
        DefaultTableModel model = (DefaultTableModel) tblTask.getModel();
        clearJTable(model);
        messages.clear();
        Comparator<TaskDTO.Output> comparing = Comparator.comparing(TaskDTO.Output::getId);
        if (sortType) {
            comparing = comparing.reversed();
        }
        if ("id".equals(sortName)) {
            taskList = taskList.stream().sorted(comparing).collect(Collectors.toList());
        }
        addDefaultTask(taskList);
        for (int i = 0; i < taskList.size(); i++) {
            TaskDTO.Output item = taskList.get(i);
            Object[] data = new Object[10];
            data[0] = String.valueOf(i + 1);
            data[1] = false;
            data[2] = item.getId();
            data[3] = TaskTypeEnum.getGroupByValue(item.getType());
            data[4] = item.getTitle();
            data[5] = getStatusName(item);
            data[6] = item.getDeadline();
            data[7] = Optional.ofNullable(projects.get(item.getProjectId())).orElse("");
            data[8] = item.getOpenedBy();
            model.addRow(data);
            messages.add(getCommitMessage(item));
        }
    }

    public JPanel getMainPanel() {
        return mainPanel;
    }

    /**
     * 生成标准commit信息
     *
     * @return
     */
    public String getCommitMessage() {
        List<String> list = Lists.newArrayListWithExpectedSize(5);
        DefaultTableModel model = (DefaultTableModel) tblTask.getModel();
        for (int i = 0; model.getRowCount() > i; i++) {
            boolean check = (boolean) model.getValueAt(i, 1);
            if (!check) {
                continue;
            }
            list.add(messages.get(i));
        }
        return list.stream().collect(Collectors.joining("\r\n"));
    }

    /**
     * 添加标准任务
     * style,check,merge
     *
     * @param taskList
     */
    public void addDefaultTask(List<TaskDTO.Output> taskList) {
        TaskDTO.Output style = new TaskDTO.Output();
        style.setId("0000");
        style.setTitle("格式修改(不影响代码运行的变动)");
        style.setStatus("");
        style.setOpenedBy("system");
        style.setDeadline("0000-00-00");
        style.setModuleType(ModuleTypeEnum.DEFAULT);
        style.setType(TaskTypeEnum.STYLE.getValue());
        taskList.add(style);
        TaskDTO.Output check = new TaskDTO.Output();
        check.setId("0000");
        check.setTitle("代码扫描修复");
        check.setStatus("");
        check.setOpenedBy("system");
        check.setDeadline("0000-00-00");
        check.setModuleType(ModuleTypeEnum.DEFAULT);
        check.setType(TaskTypeEnum.CHECK.getValue());
        taskList.add(check);
        TaskDTO.Output merge = new TaskDTO.Output();
        merge.setId("0000");
        merge.setTitle("代码合并(只是为了代码合并)");
        merge.setStatus("");
        merge.setOpenedBy("system");
        merge.setDeadline("0000-00-00");
        merge.setModuleType(ModuleTypeEnum.DEFAULT);
        merge.setType(TaskTypeEnum.MERGE.getValue());
        taskList.add(merge);
    }
}
